//
//  DownloadManager.m
//  ebook
//
//  Created by ChenNan on 16/4/26.
//  Copyright © 2016年 Moton. All rights reserved.
//

#import "DownloadManager.h"
#import "FileManager.h"
#import "EbookNetRequest.h"
#import "BaiduMobStat.h"
#import "CoreStatus.h"
#import "MISAlertController.h"
#import "SSZipArchive.h"
#import "EbookNetRequest.h"

#define kLocalZipDownloadDirectory(bookid) [NSString stringWithFormat:@"%@/%@/ZipDownload", kSaveDirectory,(bookid)]//zip文件下载及解压的路径

@interface DownloadManager(){
    
    BOOL continuDownWithNowifi;//用户点击同意非wifi环境下依旧下载
    BOOL isAlertShow;//是否显示了提示弹窗
    
    //当前下载任务的数据
    DownloadModel *currentDownload;
    __block NSArray *chapterList;
    __block NSInteger totalCount;
    __block NSInteger finishCount;
    __block BOOL needSendNoti;
    __block BOOL isDowncancel;//是否取消下载
    __block float lastpercent;
    __block BOOL isDownloading;//是否有任务正在下载
}

@property (nonatomic ,retain) NSMutableArray *downloadQueue;//下载队列
@property (nonatomic ,retain) NSURLSessionDownloadTask *operation;//下载对象

@end

@implementation DownloadManager

+ (instancetype)shareInstance
{
    static DownloadManager *model = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        model = [[DownloadManager alloc] init];
    });
    return model;
}

-(instancetype)init{
    
    if(self=[super init]){
        
        self.downloadQueue = [NSMutableArray array];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cancelTask:) name:kDownloadTaskCancelShouldDeleteQueueNotification object:nil];
        [self reloadData];
    }
    return self;
}

//重新初始化数据，需要在取到新的menu后刷新
-(void)reloadData{
    id data = [[NSUserDefaults standardUserDefaults] objectForKey:KBookCityData];
    NSDictionary *dic = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    
    _chapterContentDirectory = dic[@"data"][@"downloadurl"];
    if([_chapterContentDirectory hasSuffix:@"/"])
        _chapterContentDirectory = [_chapterContentDirectory substringToIndex:_chapterContentDirectory.length-1];
    _chapterContentDirectory = _chapterContentDirectory?_chapterContentDirectory:kDefaultChapterContentDirectory;
    
    _zipDirectory = dic[@"data"][@"zipurl"];
    if([_zipDirectory hasSuffix:@"/"])
        _zipDirectory = [_zipDirectory substringToIndex:_zipDirectory.length-1];
    _zipDirectory = _zipDirectory?_zipDirectory:kDefaultZipDirectory;
    
    _bookfileDirectory = dic[@"data"][@"bookfileurl"];
    if([_bookfileDirectory hasSuffix:@"/"])
        _bookfileDirectory = [_bookfileDirectory substringToIndex:_bookfileDirectory.length-1];
    _bookfileDirectory = _bookfileDirectory?_bookfileDirectory:kDefaultBookinfoDirectory;
}

//添加或删除队列里的对象
-(void)model:(DownloadModel *)model toQueue:(BOOL)add{
    
    if(add){
        [_downloadQueue addObject:model];
    }else{
        [_downloadQueue removeObject:model];
    }
    [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:_downloadQueue] forKey:kDownloadQueue];
}

//恢复之前的下载
-(void)restoreDownload{
    
    [self reloadData];
    NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kDownloadQueue];
    [_downloadQueue addObjectsFromArray:[[NSMutableArray alloc] initWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:data]]];
    if(_downloadQueue.firstObject)
        [self startNewDown];
}

//取消下载的通知处理
-(void)cancelTask:(NSNotification *)noti {
    
    Book *cancelBook = (Book *)noti.object;
    
    __block DownloadModel *cancelModel = nil;
    [_downloadQueue enumerateObjectsUsingBlock:^(DownloadModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if([obj.book.bookid integerValue] == [cancelBook.bookid integerValue])
            cancelModel = obj;
    }];
    
    if ([cancelModel isEqual:currentDownload]) {
        isDowncancel = YES;
        if(self.operation)[self.operation cancel];//正在下载的全本任务需要取消
        [self finishedThisAndStartNext];
    }else{
        [self model:cancelModel toQueue:NO];
    }
    
    [[NSNotificationCenter defaultCenter] postNotificationName:kDownloadTaskCancelNotification object:cancelBook];//取消任务后发送界面更新的通知，处理取消操作
}

-(DownloadModel *)currentDownload{
    
    return currentDownload;
}

//判断一本书是否在在下载队列中,返回下载队列对象
-(DownloadModel *)downloadQuequOfBook:(NSString *)bookid{
    
    __block DownloadModel *model = nil;
    [_downloadQueue enumerateObjectsUsingBlock:^(DownloadModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj.book.bookid integerValue] == [bookid integerValue]) {
            model = obj;
            *stop=YES;
        }
    }];
    
    return model;
}

//添加一个下载,是否立即开始
-(BOOL)addDownload:(DownloadModel *)download{
    
    BOOL ret = NO;
    __block BOOL hasExist = NO;
    NSArray *downloadQueueSame = [NSArray arrayWithArray:_downloadQueue];//拷贝一份，防止异步遍历时删减出错
    [downloadQueueSame enumerateObjectsUsingBlock:^(DownloadModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj.book.bookid integerValue]==[download.book.bookid integerValue] && download.downloadType==obj.downloadType) {
            hasExist = YES;
            *stop=YES;
        }
    }];
    
    if(!hasExist){
        [self model:download toQueue:YES];
    }
    
    if(!isDownloading&&_downloadQueue.count==1)
        ret = YES;
    
    if(!isDownloading)
        [self startNewDown];
    
    return ret;
}

//开始下一个下载任务
-(BOOL)startNewDown{
    
    currentDownload = [_downloadQueue firstObject];
    
    if(currentDownload){
        isDowncancel = NO;
        lastpercent = 0;
        [self downloadBook:currentDownload.book currentChapter:currentDownload.chapter chapterList:currentDownload.chapterList downloadType:currentDownload.downloadType needNoti:YES];
        return YES;
    }
    
    return NO;
}

//从下载队列中删除当前下载对象，开始开一个任务
-(void)finishedThisAndStartNext{
    isDownloading = NO;
    if (currentDownload) {
        [self model:currentDownload toQueue:NO];
    }
    [self startNewDown];
}

-(void)downloadBook:(Book *)book currentChapter:(Chapter *)chapter chapterList:(NSArray *)chapterlist downloadType:(DownloadType)downloadType needNoti:(BOOL)need
{
    if (book.bookid && downloadType == Download_all) {//全本缓存，直接下载压缩文件
        
        needSendNoti = YES;
        if(chapterlist.count>0&&[FileManager fileCountInBookDirectory:book]>=chapterlist.count)
            dispatch_async(dispatch_get_main_queue(), ^{
                if(finishCount == totalCount)
                    [self finishedThisAndStartNext];
                NSDictionary *dic = [NSDictionary dictionaryWithObjects:@[@((float)finishCount/totalCount),@(YES), book.bookid,@(NO),@(NO)] forKeys:@[@"percent", @"exist", @"bookId",@"hasCancel",@"isWait"]];
                [[NSNotificationCenter defaultCenter] postNotificationName:kFinishOneDownloadTaskNotification object:dic];
            });
        else
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                __strong Book *sbook = book;
                [self beginZipDownload:sbook];
            });
        
        return;
    }
    
    if (!book||!chapter||!chapterlist||chapterlist.count==0||!book.bookid) {
        [self finishedThisAndStartNext];
        return;
    }
    chapterList = chapterlist;
    needSendNoti = need;
    
    NSInteger location = [chapterlist indexOfObject:chapter];
    totalCount = downloadType;//需要下载的数目
    if (downloadType == Download_nowToEnd || downloadType == Download_all || ((location + totalCount) > chapterlist.count)) {//后续章节 || 位置＋个数>章节总个数
        totalCount = chapterlist.count-location;
    }
    
    //需要下载的章节
    NSMutableArray *downloadChapters = [NSMutableArray arrayWithArray:[chapterlist subarrayWithRange:NSMakeRange(location, totalCount)]];
    
    NSMutableArray *removeArray=[NSMutableArray array];
    [downloadChapters enumerateObjectsUsingBlock:^(Chapter *chapter, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([FileManager isExistBookChapters:book chapterid:chapter.chapterid]) {
            [removeArray addObject:chapter];
        }
    }];
    [downloadChapters removeObjectsInArray:removeArray];
    
    finishCount = removeArray.count;
    
    if(needSendNoti)
        dispatch_async(dispatch_get_main_queue(), ^{
            if(finishCount == totalCount)[self finishedThisAndStartNext];
            NSDictionary *dic = [NSDictionary dictionaryWithObjects:@[@((float)finishCount/totalCount),@(finishCount>=totalCount), book.bookid,@(NO),@(NO)] forKeys:@[@"percent", @"exist", @"bookId",@"hasCancel",@"isWait"]];
            [[NSNotificationCenter defaultCenter] postNotificationName:kFinishOneDownloadTaskNotification object:dic];
        });
    
    if(downloadChapters.count==0)return;
    
    dispatch_queue_t queue = dispatch_queue_create("com.downloadTask", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
        
        [self downloadBook:book chaptersArray:downloadChapters isDownAll:NO];
    });
}

- (void)downloadBook:(Book *)book chaptersArray:(NSArray *)downloadChaptersArray  isDownAll:(BOOL)all{
    
    if(!book||!book.bookid||!book.siteid)return;
    
    //需用计时器代替循环，否则进度条不更新
    __block int32_t i=0;
    dispatch_queue_t queue = dispatch_queue_create("com.timer", DISPATCH_QUEUE_CONCURRENT);
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW,0, 0);
    dispatch_source_set_event_handler(timer, ^{
        
        if(i==downloadChaptersArray.count||isDowncancel){//下载完成或用户取消了下载
            
            dispatch_source_cancel(timer);
            
        }else if(i<downloadChaptersArray.count){
            
            //下载后续五章(直接调用下载方法，而不是用队列管理的)，不用提示网络
            if(currentDownload)
                [self checkNetStatus:timer];
            
            isDownloading = YES;
            Chapter *chapter = downloadChaptersArray[i++];
            NSInteger currentIndex = [chapterList indexOfObject:chapter];
            if ((int)(chapterList.count - (currentIndex-1))<0) return;
            NSString *downurl = [self chapterContentUrl:book :chapter];
            NSString *directory = kBookDirectory(book.bookid,book.siteid);
            __unsafe_unretained typeof(self) weakSelf = self;
            [EbookNetRequest downloadFileWithURLString:downurl downloadFileProgress:^(NSProgress *downloadProgress) {
                ;
            } saveToPath:directory downloadCompletionHandler:^(NSURL *filePath, NSError *error) {
                __strong __typeof(self) strongSelf = weakSelf;
                if (error) {
                    MTLog(@"下载章节内容文件失败：%@",error);
                    NSString *path = [directory stringByAppendingPathComponent:[downurl lastPathComponent]];
                    [[NSFileManager defaultManager]removeItemAtPath:path error:nil];
                }else{
                    finishCount++;
                    //                    MTLog(@"~~~~finishCount:%d",(int)finishCount);
                    //发通知
                    if(needSendNoti)
                        [strongSelf sendProgressNotificition:book.bookid:(float)finishCount/totalCount];
                    if((finishCount==totalCount||isDowncancel)){
                        if(strongSelf.currentDownload&&self.currentDownload.downloadType!=Download_all)
                            [strongSelf finishedThisAndStartNext];
                    }
                }
            }];
        }
    });
    
    dispatch_source_set_cancel_handler(timer, ^{
        
    });
    
    dispatch_resume(timer);
}

//取消当前下载
-(void)cancelCurrentDown{
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:kDownloadTaskCancelNotification object:currentDownload.book];
        if(self.operation)[self.operation cancel];//正在下载的全本任务需要取消
        [self finishedThisAndStartNext];
    });
}

//检查网络状态，wifi状态或用户授权同意下载的情况下才继续下载
-(void)checkNetStatus:(dispatch_source_t)timer{
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        if ([CoreStatus currentNetWorkStatus] == CoreNetWorkStatusNone) {
            if(timer)dispatch_suspend(timer);
            [[NSNotificationCenter defaultCenter] postNotificationName:kDownloadTaskCancelNotification object:currentDownload.book];
            if(isAlertShow)return ;
            MISAlertController *alertController = [MISAlertController alertControllerWithTitle:@"下载失败" message:@"网络连接已断开，请检查网络设置" preferredStyle:UIAlertControllerStyleAlert];
            MISAlertAction *okAction = [MISAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(MISAlertAction *action){
                isAlertShow = NO;
                [self finishedThisAndStartNext];
            }];
            [alertController addAction:okAction];
            [alertController showInViewController:[self appTopViewController] animated:YES];
            isAlertShow = YES;
        } else if ([CoreStatus currentNetWorkStatus] != CoreNetWorkStatusWifi) {
            
            if(continuDownWithNowifi)return ;
            
            if(timer)dispatch_suspend(timer);
            if(self.operation)[self.operation suspend];
            if(isAlertShow)return ;
            MISAlertController *alertController = [MISAlertController alertControllerWithTitle:@"提示" message:@"当前非Wi-Fi状态，是否继续下载" preferredStyle:UIAlertControllerStyleAlert];
            MISAlertAction *cancelAction = [MISAlertAction actionWithTitle:@"取消下载" style:UIAlertActionStyleDefault handler:^(MISAlertAction *action) {
                [[NSNotificationCenter defaultCenter] postNotificationName:kDownloadTaskCancelShouldDeleteQueueNotification object:currentDownload.book];
                continuDownWithNowifi = NO;
                isAlertShow = NO;
                if(self.operation)[self.operation cancel];
            }];
            
            MISAlertAction *okAction = [MISAlertAction actionWithTitle:@"继续下载" style:UIAlertActionStyleDefault handler:^(MISAlertAction *action) {
                continuDownWithNowifi = YES;
                if(timer)dispatch_resume(timer);
                isAlertShow = NO;
                if(self.operation)[self.operation resume];
            }];
            
            [alertController addAction:okAction];
            [alertController addAction:cancelAction];
            [alertController showInViewController:[self appTopViewController] animated:YES];
            isAlertShow = YES;
        }
    });
}

#pragma mark - 压缩包下载
-(void)beginZipDownload:(Book *)book{
    
    NSString *downurl = [self zipUrl:book updatetime:[book.updatetime intValue]];
    NSString *directory = kBookDirectory(book.bookid,book.siteid);
    [self checkNetStatus:nil];
    isDownloading = YES;
    _operation = [EbookNetRequest downloadFileWithURLString:downurl downloadFileProgress:^(NSProgress *downloadProgress) {
        float progress = downloadProgress.fractionCompleted;
        if(progress<0.01||progress>0.99)
            MTLog(@"下载%@压缩文件进度：%f",book.bookid,progress);
        [self sendProgressNotificition:book.bookid : (progress>0.01?(progress-0.01):progress)];
        [self checkNetStatus:nil];
    } saveToPath:directory downloadCompletionHandler:^(NSURL *filePath, NSError *error) {
        if (error) {
            MTLog(@"下载压缩文件失败：%@",error);
            
            NSString *errrormsg = [[error userInfo] objectForKey:@"NSLocalizedDescription"];
            if(errrormsg.length>0&&!isAlertShow){
                MISAlertController *alertController = [MISAlertController alertControllerWithTitle:@"下载失败" message:errrormsg preferredStyle:UIAlertControllerStyleAlert];
                MISAlertAction *okAction = [MISAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(MISAlertAction *action){
                    [self cancelCurrentDown];
                    isAlertShow = NO;
                }];
                [alertController addAction:okAction];
                [alertController showInViewController:[self appTopViewController] animated:YES];
                isAlertShow = YES;
            }else{
                [self cancelCurrentDown];
            }
        }else{
            MTLog(@"下载压缩文件成功：%@",filePath);
            if(isDowncancel)return;
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                NSString *filePath = [directory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.zip",book.bookid]];
                [SSZipArchive unzipFileAtPath:filePath toDestination:directory progressHandler:^(NSString * _Nonnull entry, unz_file_info zipInfo, long entryNumber, long total) {
                    if(entryNumber<3||entryNumber>total-3)//只显示前后部分日志
                        MTLog(@"正在解压缩%@：%d/%d",book.bookid,(int)entryNumber,(int)total);
                    else if(entryNumber==3)
                        MTLog(@"正在解压缩... (防刷屏，中间不再输出日志，快结束时再输出)");
                    
                    if (entryNumber==total) {//根据压缩文件解压的文件数判断是否完成，而不是completionHandler
                        MTLog(@"下载%@的压缩文件解压完成，即将开始下一个任务",book.bookid);
                        [self finishedThisAndStartNext];//下载解压完成，开始下一个任务
                        [self sendProgressNotificition:book.bookid : 1.0f];
                    }
                } completionHandler:^(NSString * _Nonnull path, BOOL succeeded, NSError * _Nonnull error) {
                    [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];//解压完成之后删除zip文件
                    if(!succeeded||error)[self finishedThisAndStartNext];//解压失败，开始下一个任务
                }];
            });
        }
    }];
}

//通知界面主进程更新进度
- (void)sendProgressNotificition:(NSString *)bookid : (float)progress
{
    if (progress>lastpercent+0.01f||lastpercent>0.99||lastpercent<0.01f) {//只有进度差大于0.01时才更新界面，避免频繁更新占用主进程造成界面卡死(上次进度已经超过了0.99的继续)
        lastpercent = progress;
        dispatch_async(dispatch_get_main_queue(), ^{
            NSDictionary *dic = [NSDictionary dictionaryWithObjects:@[@(progress), @(NO), bookid,@(isDowncancel),@(NO)] forKeys:@[@"percent", @"exist", @"bookId",@"hasCancel",@"isWait"]];
            [[NSNotificationCenter defaultCenter] postNotificationName:kFinishOneDownloadTaskNotification object:dic];
        });
    }
}

//网络章节内容获取,获取完成存储到本地
-(NSString *)getNetChaptercontent:(Book *)book chapter:(Chapter *)chapter{
    
    NSString *chapterContent = nil;
    NSString *urlStr = [self chapterContentUrl:book:chapter];
//    urlStr = [urlStr stringByReplacingOccurrencesOfString:@"static.5kxs.net" withString:@"static.51xs.me"];//模拟404错误
    NSURL *URL = [NSURL URLWithString:urlStr];
    NSError *error;
    
    NSURLRequest * urlRequest = [NSURLRequest requestWithURL:URL];
    NSURLResponse * response = nil;
    __strong NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
                                                   returningResponse:&response
                                                               error:&error];
    
    NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
    int responseStatusCode = (int)[httpResponse statusCode];
    if (responseStatusCode>400||error) {
        
        chapterContent = [NSString stringWithFormat:@"%@ (错误码:%d)",responseStatusCode==404?kContentErrorServerNotFoundInfo:kContentErrorNoNetInfo,responseStatusCode];
        data = [chapterContent dataUsingEncoding:kTxtEncoding];
        
    } else{
        chapterContent = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        if(!chapterContent)chapterContent = [[NSString alloc] initWithData:data encoding:kTxtEncoding];
    }
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [FileManager writeBook:book chapterid:chapter.chapterid withData:data];
    });
    
    return chapterContent;
}

//当前显示的是错误页内容
-(BOOL)isErrorContent:(NSString *)content{
    
    NSArray *notContent = @[kContentErrorServerNotFoundInfo,kContentErrorNoNetInfo];
    for (NSString *no in notContent) {
        if([content hasPrefix:no])
            return YES;
    }
    return NO;
}

//本地章节内容获取
-(NSString *)getLocalChaptercontent:(NSString *)bookId chapterId:(NSString *)chapterId{
    
    //如果是压缩包下载到本地，则直接从这个路径获取章节内容
    NSString *path = [kLocalZipDownloadDirectory(bookId) stringByAppendingFormat:@"/%@.txt",chapterId];
    NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
    NSString *chapterContent= [[NSString alloc] initWithData:data encoding: CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)];
    return chapterContent;
}

//Dictionary类型的列表转为Chapter对象类型的列表
- (NSMutableArray *)dictListToChapterList:(NSArray *)array{
    NSMutableArray *list = [NSMutableArray array];
    [array enumerateObjectsUsingBlock:^(NSDictionary *dic, NSUInteger idx, BOOL * _Nonnull stop) {
        
        Chapter *chapter = [[Chapter alloc] initWithDictionary:dic];
        if([chapter.chaptertype integerValue]==0)
            [list addObject:chapter];
    }];
    return list;
}

//服务器上章节内容文件地址
-(NSString *)chapterContentUrl :(Book *)book :(Chapter *)chapter{
    
    if(!book||!book.bookid||!chapter||!chapter.chapterid){
        MTLog(@"txtUrl null book:%@,chapter:%@",book,chapter);
        return nil;
    }
    NSString *format = @"%@/%@/%d/%@/%@.txt?time=%d";
    NSString *url = [NSString stringWithFormat:format,_chapterContentDirectory,book.siteid,[book.bookid intValue]/1000,book.bookid,chapter.chapterid,[chapter.updatetime intValue]];
    url = [self cdnUrl:url];
    MTLog(@"chapterContentUrl:%@",url);
    
    return url;
}

//全本压缩包地址
-(NSString *)zipUrl:(Book *)book updatetime:(int)time{
    
    if(!book||!book.bookid||!book.siteid){
        MTLog(@"zipUrl null book:%@",book);
        return nil;
    }
    NSString *format = @"%@/%@/%d/%@/%@.zip?time=%d";
    NSString *url = [NSString stringWithFormat:format,_zipDirectory,book.siteid,[book.bookid intValue]/1000,book.bookid,book.bookid,time];
    url = [self cdnUrl:url];
    MTLog(@"zipUrl:%@",url);
    
    return url;
}

-(NSString *)cdnUrl:(NSString *)url{
    
    NSString *cdnUrl;
//    return url;  //TODO 测试不要鉴权
  
    NSString *cdnSupplier = @"TX";  //"ALI"(阿里云)或者"TX"（腾讯云）
   
    if([cdnSupplier isEqualToString:@"TX"]){
        NSInteger headLength = [url hasPrefix:@"https://"]?8:7;//@"http://"字符长度
        if (url.length>headLength) {
            NSInteger firstInde = [[url substringFromIndex:headLength] rangeOfString:@"/"].location+headLength;
            NSString *part1 = [url substringToIndex:firstInde];//主机地址
            NSString *part2 = [url substringFromIndex:firstInde];//相对路径（包含参数）
            NSString *part3 = part2;//去掉参数后的路径
            NSRange qrange = [part2 rangeOfString:@"?"];
            if (qrange.length>0) {
                part3 = [part2 substringToIndex:qrange.location];//
            }
            NSString *time = [[NSUserDefaults standardUserDefaults] objectForKey:kExptime];
            NSString *hashStr = [NSString stringWithFormat:@"%@%@%@",kCDNkey,part3,time];
            NSString *md5 = [EbookNetRequest MD5:hashStr];
            
            cdnUrl = qrange.length>0?[NSString stringWithFormat:@"%@&sign=%@&t=%@",url,md5,time]:[NSString stringWithFormat:@"%@?sign=%@&t=%@",url,md5,time];
        }
    }else if ([cdnSupplier isEqualToString:@"ALI"]){
        NSInteger headLength = [url hasPrefix:@"https://"]?8:7;//@"http://"字符长度
        if (url.length>headLength) {
            NSInteger firstInde = [[url substringFromIndex:headLength] rangeOfString:@"/"].location+headLength;
            NSString *part1 = [url substringToIndex:firstInde];//主机地址
            NSString *part2 = [url substringFromIndex:firstInde];//相对路径（包含参数）
            NSString *part3 = part2;//去掉参数后的路径
            NSRange qrange = [part2 rangeOfString:@"?"];
            if (qrange.length>0) {
                part3 = [part2 substringToIndex:qrange.location];
            }
            NSString *time = [[NSUserDefaults standardUserDefaults] objectForKey:kExptime];
            NSString *hashStr = [NSString stringWithFormat:@"%@%@%@",kCDNkey,part3,time];
            NSString *md5 = [EbookNetRequest MD5:hashStr];
            
            cdnUrl = [NSString stringWithFormat:@"%@/%@/%@%@",part1,md5,time,part2];
        }
    }
    
    return cdnUrl;
}

- (UIViewController *)appTopViewController
{
    UIViewController *appRootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
    UIViewController *topVC = appRootVC;
    while (topVC.presentedViewController) {
        topVC = topVC.presentedViewController;
    }
    return topVC;
}

- (void)dealloc {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end
